home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** MPBlitter a simple blitter for MP Tasks.
- **
- ** by Matthew Xavier Mora, Apple Developer Technical Support
- **
- ** File: MPBlitter.c
- **
- ** Copyright © 1996-1997 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DSC Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
- */
-
- /*
- This is a simple blitter to allow my MPtask to blit to the screen.
- I was going to add masked blitting that honored the visRgn and clip
- regions so that it didn't color outside the lines. I haven't done that
- yet.
-
- Since the original SortPicts program that I used only works with
- 8 bit images I didn't spend any time adding any other cases to the
- blitter. If I ever get time I'll finish the blitter to be more useful
- as a generic CopyBits routine for MP.
-
- */
-
- #include "MPBlitter.h"
- #include <Multiprocessing.h>
- //#include "MyInterruptSafeDebug.h"
- //-----------------------------------------------------------------------------------
- pascal void MPCopyBits(BitMapPtr srcBits, BitMapPtr dstBits,const Rect *srcRect,const Rect *dstRect,const short mode,const RgnHandle mask)
- //-----------------------------------------------------------------------------------
- {
- #pragma unused (mode)
- PixMapPtr srcPM;
- PixMapPtr dstPM;
- long dstLeft;
- long dstRight;
- long srcLeft;
- long srcRowBytes;
- long dstRowBytes;
- char * srcRow;
- char * dstRow;
- char * srcPtr;
- char * dstPtr;
- long height;
- long width;
- long i;
- long offset;
- MPCriticalRegionID blitterBusy;
-
- // mask better contain a MPCriticalRegionID instead of a mask region handle!
- blitterBusy = (MPCriticalRegionID)mask;
- (void)MPEnterCriticalRegion(blitterBusy, kDurationForever);
-
- if (dstRect->top == dstRect->bottom) {
- // a simple flag to say that the image is not ready
- goto exit;
- }
-
- srcPM = (PixMapPtr) srcBits;
- dstPM = (PixMapPtr) dstBits;
-
- srcRow = (char *) srcPM->baseAddr;
- dstRow = (char *) dstPM->baseAddr;
-
- srcRowBytes = (srcPM->rowBytes & 0x3fff);
- dstRowBytes = (dstPM->rowBytes & 0x3fff);
-
- // get the bit offset to the src left edge
- srcLeft = srcRect->left - srcPM->bounds.left;
- srcLeft *= srcPM->pixelSize;
- srcRow += srcLeft;
-
- // get the bit offset to the dst left and right edges
- dstLeft = dstRect->left - dstPM->bounds.left;
- dstLeft *= dstPM->pixelSize;
- dstRight = dstRect->right - dstPM->bounds.left;
- dstRight *= dstPM->pixelSize;
- dstRow += dstLeft >> 3;
-
- // offset the src and dst ptrs to the first row
- offset = srcRect->top - srcPM->bounds.top;
- offset *= srcRowBytes ;
- srcRow += offset;
-
- offset = dstRect->top - dstPM->bounds.top;
- offset *= dstRowBytes ;
- dstRow += offset;
-
- height = dstRect->bottom - dstRect->top - 1;
- width = dstRect->right - dstRect->left - 1;
- width *= (dstPM->pixelSize >> 3);
-
- if (srcPM->pixelSize != dstPM->pixelSize) {
- // ACK!
- //InterruptSafeDebug ("\pPixel depth needs to be 8 bits! \n");
-
- }
- switch (dstPM->pixelSize) {
- case 8:
- while (height--) {
- srcPtr = srcRow;
- dstPtr = dstRow;
-
- for (i = 0 ;i < width >> 2;i++)
- {
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
-
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
-
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
- }
-
- switch ( width % 4) {
- case 3:
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
- case 2:
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
- case 1:
- *dstPtr = *srcPtr;
- ++srcPtr;
- ++dstPtr;
- }
- srcRow += srcRowBytes;
- dstRow += dstRowBytes;
- }
- break;
- case 16:
- break;
- case 32:
- break;
- }
-
- exit:
- (void)MPExitCriticalRegion(blitterBusy);
- }
-
-
- static pascal void CopyBlit(PixMapPtr srcPM, PixMapPtr dstPM, Rect *srcRect, Rect *dstRect)
- {
- long dstLeft;
- long dstRight;
- long * srcRow;
- long * dstRow;
- register long * srcPtr;
- register long * dstPtr;
- long leftMask;
- long notLeftMask;
- long rightMask;
- long notRightMask;
- long dstLong;
- short dstLongs;
- short localheight;// = height;
- long offset;
- long timesCopy;
-
- short height;
- long srcRowBytes;
- long dstRowBytes;
- long srcLeft;
-
- localheight = height = srcRect->bottom - srcRect->top; // No scaling allowed
-
- srcRowBytes = srcPM->rowBytes & 0x3fff;
- dstRowBytes = dstPM->rowBytes & 0x3fff;
-
- // get the bit offset to the src left edge
- srcLeft = (srcRect->left - srcPM->bounds.left) * srcPM->pixelSize;
-
- srcRow = (long *) srcPM->baseAddr;
- dstRow = (long *) dstPM->baseAddr;
-
- // offset the src ptr to the first long
- srcRow += srcLeft >> 5;
-
- // get the bit offset to the dst left and right edges
- dstLeft = (dstRect->left - dstPM->bounds.left) * dstPM->pixelSize;
- dstRight = (dstRect->right - dstPM->bounds.left) * dstPM->pixelSize;
-
- // get the number of middle longs to do minus the left edge long
- dstLongs = ((dstRight - dstLeft) >> 5) - 1;
-
- // offset the dst Ptr to the first long
- dstRow += dstLeft >> 5;
-
- // now compute left and right masks for the dst
- dstLeft &= 0x1f;
- leftMask = ( 1 << dstLeft ) - 1;
- notLeftMask = ~leftMask;
-
- dstRight &= 0x1f;
- notRightMask = ( 1 << dstRight ) - 1;
- rightMask = ~notRightMask;
-
- // offset the src and dst ptrs to the first row
- offset = (srcRect->top - srcPM->bounds.top) * srcRowBytes;
- srcRow += offset >> 2;
-
- offset = (dstRect->top - dstPM->bounds.top) * dstRowBytes;
- dstRow += offset >>2;
-
- /* check if we need to do the left and right mask */
- if ( leftMask )
- {
- if ( notLeftMask == 0 )
- {
- leftMask = 0;
- dstLongs++;
- }
- }
-
- if ( rightMask )
- {
- if ( notRightMask == 0 )
- {
- rightMask = 0;
- dstLongs++;
- }
- }
-
- //for ( ; localheight >= 0; --localheight )
- // changing the above 'for()' to the below 'while()' is what made this blit routine
- // faster than CopyBits - a speed improvement equal to all other changes I had made
- // previously. (about 4 to 5 milliseconds, in case you were wondering)
- // Lesson: the true bottlenecks are not always the obvious ones
- while (localheight--)
- {
- srcPtr = srcRow;
- dstPtr = dstRow;
-
- /* do the masked left edge */
- if ( leftMask )
- {
- dstLong = *srcPtr++ & leftMask;
- dstLong |= *dstPtr & notLeftMask;
- *dstPtr++ = dstLong;
- }
-
- /* do the middle longs with Duff's device */
- timesCopy = (dstLongs + 15) >> 4;
-
- switch( dstLongs & 0xF )
- {
- case 0: do
- { *dstPtr++ = *srcPtr++;
- case 15: *dstPtr++ = *srcPtr++;
- case 14: *dstPtr++ = *srcPtr++;
- case 13: *dstPtr++ = *srcPtr++;
- case 12: *dstPtr++ = *srcPtr++;
- case 11: *dstPtr++ = *srcPtr++;
- case 10: *dstPtr++ = *srcPtr++;
- case 9: *dstPtr++ = *srcPtr++;
- case 8: *dstPtr++ = *srcPtr++;
- case 7: *dstPtr++ = *srcPtr++;
- case 6: *dstPtr++ = *srcPtr++;
- case 5: *dstPtr++ = *srcPtr++;
- case 4: *dstPtr++ = *srcPtr++;
- case 3: *dstPtr++ = *srcPtr++;
- case 2: *dstPtr++ = *srcPtr++;
- case 1: *dstPtr++ = *srcPtr++;
- } while( --timesCopy > 0 );
- }
-
- /* do the masked right edge */
- if ( rightMask )
- {
- dstLong = *srcPtr & rightMask;
- dstLong |= *dstPtr & notRightMask;
- *dstPtr = dstLong;
- }
-
- /* bump to the next row */
- srcRow += srcRowBytes >>2;
- dstRow += dstRowBytes >>2;
- }
- }
-
- static pascal void betterMPCopyBits(BitMapPtr srcBits, BitMapPtr dstBits,
- Rect *srcRect, Rect *dstRect,
- short mode, RgnHandle mask)
- {
- #pragma unused (mode,mask)
- CopyBlit((PixMapPtr) srcBits, (PixMapPtr) dstBits,srcRect, dstRect);
- }
-